package ruleengine

import (
	"fmt"
	"strings"
)

// ========= 规则引擎 =========
type RuleEngine struct {
	ctx *Context
}

func NewRuleEngine() *RuleEngine {
	engine := &RuleEngine{
		ctx: NewContext(),
	}

	// 注册内置函数
	engine.RegisterBuiltinFunctions()

	return engine
}

func (e *RuleEngine) SetVariable(name string, value interface{}) {
	e.ctx.SetVariable(name, value)
}

func (e *RuleEngine) RegisterFunction(name string, fn func(...interface{}) interface{}) {
	e.ctx.RegisterFunction(name, fn)
}

func (e *RuleEngine) RegisterBuiltinFunctions() {
	// 数学函数
	e.RegisterFunction("min", func(args ...interface{}) interface{} {
		if len(args) < 1 {
			return 0
		}
		min := toFloat(args[0])
		for _, arg := range args[1:] {
			val := toFloat(arg)
			if val < min {
				min = val
			}
		}
		return min
	})

	e.RegisterFunction("max", func(args ...interface{}) interface{} {
		if len(args) < 1 {
			return 0
		}
		max := toFloat(args[0])
		for _, arg := range args[1:] {
			val := toFloat(arg)
			if val > max {
				max = val
			}
		}
		return max
	})

	e.RegisterFunction("abs", func(args ...interface{}) interface{} {
		if len(args) != 1 {
			return 0
		}
		val := toFloat(args[0])
		if val < 0 {
			return -val
		}
		return val
	})

	e.RegisterFunction("round", func(args ...interface{}) interface{} {
		if len(args) != 1 {
			return 0
		}
		val := toFloat(args[0])
		return float64(int(val + 0.5))
	})

	// 逻辑函数
	e.RegisterFunction("not", func(args ...interface{}) interface{} {
		if len(args) != 1 {
			return false
		}
		return !isTruthy(args[0])
	})

	// 字符串函数
	e.RegisterFunction("concat", func(args ...interface{}) interface{} {
		var builder strings.Builder
		for _, arg := range args {
			builder.WriteString(fmt.Sprintf("%v", arg))
		}
		return builder.String()
	})

	e.RegisterFunction("contains", func(args ...interface{}) interface{} {
		if len(args) != 2 {
			return false
		}
		str := fmt.Sprintf("%v", args[0])
		substr := fmt.Sprintf("%v", args[1])
		return strings.Contains(str, substr)
	})

	e.RegisterFunction("length", func(args ...interface{}) interface{} {
		if len(args) != 1 {
			return 0
		}
		str := fmt.Sprintf("%v", args[0])
		return float64(len(str))
	})
}

func (e *RuleEngine) Evaluate(expression string) interface{} {
	parser := NewParser(expression)
	expr := parser.Parse()
	return expr.Interpret(e.ctx)
}
